package laravel;

import entity_model.Entity;
import entity_model.EntityModel;
import javafx.collections.ObservableMap;
import laravel.mvc.EntityFacade;
import laravel.mvc.model.AbstractModel;
import laravel.mvc.model.BaseSubModel;
import laravel.mvc.model.Model;
import laravel.mvc.view.LeftMenu;
import utils.Utils;
import utils.VirtualFolder;
import utils.files.File;
import utils.titles.Title;
import php.code.instructions.VariableDeclaration;

import java.util.ArrayList;
import java.util.List;
import java.util.prefs.Preferences;

import static php.code.Visibility.PUBLIC;

public class Laravel {
    public static final Preferences PREFERENCES = Preferences.userNodeForPackage(Laravel.class);
    public static final VirtualFolder ROOT_FOLDER = new VirtualFolder(PREFERENCES.get("ROOT_FOLDER", null));

    static {
        ROOT_FOLDER.addListener((observable, oldValue, newValue) -> {
            if (newValue != null)
                PREFERENCES.put("ROOT_FOLDER", newValue.getName());
        });
    }

    public static final VirtualFolder APP_FOLDER = ROOT_FOLDER.create("app");

    public final List<File> files = new ArrayList<>();

    public final ObservableMap<Title, Model> models = Utils.observableMap();
    public final ObservableMap<Entity, BaseSubModel> baseSubModels = Utils.observableMap();
    private final List<CommandListener> listeners = new ArrayList<>();

    public AbstractModel get(Entity entity) {
        return entity.isAbstract() ? baseSubModels.get(entity) : models.get(entity.getTitle());
    }

    private final Routes routes = new Routes();
    private final LeftMenu leftMenu = new LeftMenu();
    private final EntityModel entityModel;

    public Laravel(EntityModel entityModel){
        this.entityModel = entityModel;
    }

    public void execute() {
        for (Entity entity : entityModel.entities)
            new EntityFacade(this, entity).createComponents();

        completeUser();

        finish();
    }

    private void finish() {
        for (CommandListener listener : listeners)
            listener.onFinish();
    }

    public void save(){
//        getRoutes().save();
//        getLeftMenu().save();

        for(File file : files)
            file.save();
    }

    public Routes getRoutes() {
        return routes;
    }

    public LeftMenu getLeftMenu() {
        return leftMenu;
    }

    public void setOnFinished(CommandListener listener) {
        listeners.add(listener);
    }

    public void completeUser() {
        Model users = models.get(Title.fromCapitalized("Users"));

        users.entityClass.addInterfaces("Illuminate\\Auth\\UserInterface", "Illuminate\\Auth\\Reminders\\RemindableInterface");

        users.entityClass.createMethod(PUBLIC, Title.fromLowerCamel("getAuthIdentifier"))
                .returns("$this->getKey()")
                .doc(
                        "Get the unique identifier for the user.",
                        "",
                        "@return mixed"
                );

        users.entityClass.createMethod(PUBLIC, Title.fromLowerCamel("getAuthPassword"))
                .returns("$this->password")
                .doc(
                        "Get the password for the user.",
                        "",
                        "@return string"
                );

        users.entityClass.createMethod(PUBLIC, Title.fromLowerCamel("getRememberToken"))
                .returns("$this->remember_token")
                .doc(
                        "Get the token value for the \"remember me\" session.",
                        "",
                        "@return string"
                );

        users.entityClass.createMethod(PUBLIC, Title.fromLowerCamel("setRememberToken"), new VariableDeclaration("value"))
                .returns("$this->remember_token = $value")
                .doc(
                        "Set the token value for the \"remember me\" session.",
                        "",
                        "@param  string  $value",
                        "@return void"
                );

        users.entityClass.createMethod(PUBLIC, Title.fromLowerCamel("getRememberTokenName"))
                .returns("'remember_token'")
                .doc(
                        "Get the column name for the \"remember me\" token.",
                        "",
                        "@return string"
                );

        users.entityClass.createMethod(PUBLIC, Title.fromLowerCamel("getReminderEmail"))
                .returns("$this->email")
                .doc(
                        "Get the e-mail address where password reminders are sent.",
                        "",
                        "@return string"
                );

    }
}
